package chapter4_对象组合.线程安全性委托;

import annotation.NotThreadSafe;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 委托失效
 *
 * 分析：lower与upper虽然都是线程安全的AtomicInteger，但是他们之间并不是相互独立，有不变性条件:lower<=upper使两者之间有依赖关系，如果两个
 * 线程分别执行setLower(5)、setUpper(4)，则在乱序下都有可能执行成功
 * 结论：线程不安全
 * 解决：通过加锁机制保障upper和lower的复合操作的原子性
 */
@NotThreadSafe
public class NumberRange {
    // 不变性条件： lower <= upper
    private final AtomicInteger lower = new AtomicInteger();//1 setLower(5)
    private final AtomicInteger upper = new AtomicInteger();//7 setUpper(4)

    public void setLower(int i) {
        //注意 ------不安全的"先检查后执行"
        if (i > upper.get()) {
            throw new IllegalArgumentException("can't set lower to " + i + " > upper");
        }
        lower.set(i);
    }

    public void setUpper(int i) {
        //注意 ------不安全的"先检查后执行"
        if (i < lower.get()) {
            throw new IllegalArgumentException("can't set upper to " + i + " < lower");
        }
        upper.set(i);
    }

    public boolean isInRange(int i) {
        return (i >= lower.get() && i <= upper.get());
    }
}
